﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace jsonar
{
	/// <summary>
	/// JSON数组
	/// </summary>
	public sealed class Arr : Json, IEnumerable<Json>
	{
		public readonly static Arr NullINSTANCE = null;
		//public readonly static Arr EmptyINSTANCE = new Arr();

        public override int Count() { return this.count; }
        private int count = 0;

        private Json[] entries = null;

		public Arr(int capacity = 0) { this.entries = new Json[Math.Max(capacity, 5)]; }
		private Arr() { }

		public override Arr getValue(Arr dft) { return this; }

		private void add(Json json)
		{
			if (this.entries == null) return;
			if (json == null) json = Null.INSTANCE;
			if (this.count >= this.entries.Length)
			{
				Json[] arr = new Json[this.entries.Length * 2];
				Array.Copy(this.entries, 0, arr, 0, this.count);
				this.entries = arr;
			}
			this.entries[this.count++] = json;
		}

		/// <summary>
		/// 追加
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="value"></param>
		/// <returns>this</returns>
		public Arr Add<T>(T value) { this.add(GetJson(value)); return this; }
		/// <summary>
		/// 追加
		/// </summary>
		/// <param name="value"></param>
		/// <param name="deep">对object的解析深度，0不解析</param>
		/// <param name="each">value是数组时，是否将每项添加，而不是整体作为一项添加</param>
		/// <returns>this</returns>
		public Arr Add(IEnumerable value, int deep = 0, bool each = false) 
		{
			Json jb = GetJson(value, deep);
			if (!each || !(jb is Arr))
			{
				this.add(jb);
				return this;
			}

			Arr ja = jb as Arr;
			if (ja.count < 1) return this;
			foreach (Json j in ja)
			{
				this.add(j);
			}
			return this;
		}
		/// <summary>
		/// 追加
		/// </summary>
		/// <param name="value"></param>
		/// <param name="deep">对object的解析深度，0不解析</param>
		/// <returns>this</returns>
		public Arr Add(object value, int deep = 0) { this.add(GetJson(value, deep)); return this; }
		/// <summary>
		/// 追加一个空Obj
		/// </summary>
		/// <param name="capacity"></param>
		/// <returns>新Obj</returns>
		public Obj AddObj(int capacity = 0) { Obj obj = new Obj(capacity); this.add(obj); return obj; }
		/// <summary>
		/// 追加一个空Arr
		/// </summary>
		/// <param name="capacity"></param>
		/// <returns>新Arr</returns>
		public Arr AddArr(int capacity = 0) { Arr arr = new Arr(capacity); this.add(arr); return arr; }
		///// <summary>
		///// 获取或者追加Obj
		///// </summary>
		///// <param name="index"></param>
		///// <returns></returns>
		//public Obj GetOrAddObj(int index, bool replace = false) 
		//{
		//	Obj obj = this.GetChild<Obj>(index, null);
		//	if (obj == null) {
		//		obj = new Obj();
		//	} 
		//	this.add((obj = new Obj())); 
		//	return obj; 
		//}
		//public Arr GetOrAddArr(int index) 
		//{ 
		//	Arr arr = this.GetChild<Arr>(index, null); 
		//	if (arr == null) this.Add((arr = new Arr())); 
		//	return arr; 
		//}

		/// <summary>
		/// 替换，必需存在
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="index">负数：反向位置</param>
		/// <param name="value"></param>
		/// <returns>this</returns>
		public Arr Replace<T>(int index, T value)
		{
			if (index >= this.count || (index < 0 && (index += this.count) < 0)) return this;
			this.entries[index] = GetJson(value);
			return this;
		}
		/// <summary>
		/// 替换，必需存在
		/// </summary>
		/// <param name="index">负数：反向位置</param>
		/// <param name="value"></param>
		/// <param name="deep">对object的解析深度，0不解析</param>
		/// <returns>this</returns>
		public Arr Replace(int index, IEnumerable value, int deep = 0)
		{
			if (index >= this.count || (index < 0 && (index += this.count) < 0)) return this;
			this.entries[index] = GetJson(value, deep);
			return this;
		}
		/// <summary>
		/// 替换，必需存在
		/// </summary>
		/// <param name="index">负数：反向位置</param>
		/// <param name="value"></param>
		/// <param name="deep">对object的解析深度，0不解析</param>
		/// <returns>this</returns>
		public Arr Replace(int index, object value, int deep = 0)
		{
			if (index >= this.count || (index < 0 && (index += this.count) < 0)) return this;
			this.entries[index] = GetJson(value, deep);
			return this;
		}

		/// <summary>
		/// 删除
		/// </summary>
		/// <param name="index">负数：反向位置</param>
		/// <returns>this</returns>
		public Arr Remove(int index)
		{
			if (index >= this.count || (index < 0 && (index += this.count) < 0)) return this;
			if (--this.count > index) Array.Copy(this.entries, index + 1, this.entries, index, this.count - index);
			return this;
		}

		public override bool hasChild() { return this.count > 0; }

		/// <summary>
		/// 获取子项
		/// </summary>
		/// <param name="index">负数：反向位置</param>
		/// <returns></returns>
		public override Json getChild(int index) 
		{
			if (index >= this.count || (index < 0 && (index += this.count) < 0)) return Null.INSTANCE;
			return this.entries[index];
		}

		public IEnumerator<Json> GetEnumerator()
		{
			if (this.count < 1) yield break;
			int idx = 0;
			while (idx < this.count) { yield return this.entries[idx++]; }
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		public override string ToString()
		{
			if (this.count < 1) return "null";
			System.Text.StringBuilder sb = new System.Text.StringBuilder(100);
			sb.Append("[");
			int idx = -1;
			while (++idx < this.count)
			{
				if (idx > 0) sb.Append(",");
				sb.Append(this.entries[idx].ToString());
			}
			sb.Append("]");
			return sb.ToString();
		}
		public override string toHtml()
		{
			if (this.count < 1) return "null";
			System.Text.StringBuilder sb = new System.Text.StringBuilder(100);
			sb.Append("<div class=\"JA\">[");
			int idx = -1;
			while (++idx < this.count)
			{
				if (idx > 0)
				{
					sb.Append(",");
					sb.Append("<br/>");
				}
				sb.Append(this.entries[idx].toHtml());
			}
			sb.Append("]</div>");
			return sb.ToString();
		}
	}
}
